//class BufferedInputHandler;

#ifndef __EventHandlers_h_
#define __EventHandlers_h_
#include <OIS/OIS.h>
#include <CEGUI/CEGUI.h>
#include "Tools/Tool.h"

class BufferedInputHandler : public Ogre::FrameListener, public OIS::KeyListener, public OIS::MouseListener
{
private:
	
	// continue rendering
    bool mContinue;
	bool eventsToCEGUI;
    OIS::Keyboard *mKeyboard;
    OIS::Mouse *mMouse;
	Tool *tool;
public:        

    BufferedInputHandler(OIS::Keyboard *keyboard = 0, OIS::Mouse *mouse = 0, Tool *ap=0)
    {
		mContinue = true;
		eventsToCEGUI = true;
        if (keyboard)
            keyboard->setEventCallback(this);

        if (mouse)
            mouse->setEventCallback(this);
		mKeyboard = keyboard;
		mMouse = mouse;
		tool = ap;
    }

	~BufferedInputHandler(){
	}

	CEGUI::MouseButton convertOISMouseButtonToCegui(int buttonID)
	{
		switch (buttonID)
		{
		case 0: return CEGUI::LeftButton;
		case 1: return CEGUI::RightButton;
		case 2:	return CEGUI::MiddleButton;
		case 3: return CEGUI::X1Button;
		default: return CEGUI::LeftButton;
		}
	};

	virtual bool frameStarted(const Ogre::FrameEvent &evt)
    {
		//return false;
        if(mMouse)
            mMouse->capture();
        if(mKeyboard) 
            mKeyboard->capture();
		if(tool)
			tool->updateGraphics(evt);
        return mContinue && !Constants::instance()->isEnd();
    }

	bool quit()
    {
        mContinue = false;
        return true;
    }

    // KeyListener
    bool keyPressed(const OIS::KeyEvent &e) { 
		
		if(eventsToCEGUI){
			//inject key events to CEGUI
					
			CEGUI::System *sys = CEGUI::System::getSingletonPtr();
			sys->injectKeyDown(e.key);
			sys->injectChar(e.text);
		}
		if(e.key==OIS::KC_ESCAPE)
			tool->end();
		tool->keyPressed(e);
		
		return mContinue;
	}

    bool keyReleased(const OIS::KeyEvent &e) { 

		if(e.key == OIS::KC_ESCAPE)
			mContinue=false;
		if(eventsToCEGUI)
			CEGUI::System::getSingleton().injectKeyUp(e.key);
		tool->keyReleased(e);
		return mContinue;
	}

    // MouseListener
    bool mouseMoved(const OIS::MouseEvent &arg) { 
		
		if(eventsToCEGUI)
			CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
		tool->mouseMoved(arg);
		return true;
	}

    bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) { 
		
		tool->mousePressed(arg);
		if(eventsToCEGUI)
			CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
		return true;
	}

    bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id) { 
		if(eventsToCEGUI)
			CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
		return true; 
	}

	void changeTool(Tool *t){
		tool=t;
	}

	void sendEventsToCEGUI(bool b){
		eventsToCEGUI=b;
	}

};

#endif 